"""
WebRTC服务器模块
用于将RTSP视频流转换为WebRTC
"""

import asyncio
import logging
import os
import cv2
import fractions
import json
import time
import numpy as np
from typing import Dict, Any, Optional, List
from aiohttp import web
from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription
from aiortc.contrib.media import MediaRelay, MediaBlackhole
from av import VideoFrame

# 配置日志
logger = logging.getLogger(__name__)

# 媒体中继，用于共享视频帧
relay = MediaRelay()

class RTSPVideoStreamTrack(MediaStreamTrack):
    """
    RTSP视频流轨道，用于从RTSP视频流读取帧并转换为WebRTC
    """
    
    kind = "video"
    
    def __init__(self, rtsp_url: str, stream_id: str):
        """
        初始化视频轨道
        
        Args:
            rtsp_url: RTSP视频流地址
            stream_id: 流ID，用于标识
        """
        super().__init__()
        self.rtsp_url = rtsp_url
        self.stream_id = stream_id
        self.cap = None
        self.running = True
        self.frame_counter = 0
        self.last_frame = None
        self.last_frame_time = 0
        self.reconnect_attempts = 0
        self.max_reconnect_attempts = 5
        self.reconnect_delay = 2.0  # 重连延迟（秒）
        
        # 启动视频捕获线程
        self.start_capture()
    
    def start_capture(self) -> bool:
        """
        启动视频捕获
        
        Returns:
            是否成功启动
        """
        try:
            if self.cap is not None:
                self.cap.release()
            
            logger.info(f"开始连接RTSP流: {self.rtsp_url}")
            self.cap = cv2.VideoCapture(self.rtsp_url)
            
            # 设置缓冲区大小为1，尽量只保留最新帧
            self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
            
            if not self.cap.isOpened():
                logger.error(f"无法打开RTSP流: {self.rtsp_url}")
                return False
            
            # 读取一帧测试连接
            ret, frame = self.cap.read()
            if not ret:
                logger.error(f"无法从RTSP流读取帧: {self.rtsp_url}")
                return False
            
            self.last_frame = frame
            self.last_frame_time = time.time()
            self.reconnect_attempts = 0
            logger.info(f"成功连接RTSP流: {self.rtsp_url}")
            return True
            
        except Exception as e:
            logger.error(f"连接RTSP流失败: {e}")
            return False
    
    async def recv(self):
        """
        接收视频帧
        
        Returns:
            视频帧
        """
        if not self.running:
            raise Exception("视频流已停止")
        
        # 如果没有捕获器或捕获器已关闭，尝试重新连接
        if self.cap is None or not self.cap.isOpened():
            if self.reconnect_attempts < self.max_reconnect_attempts:
                logger.warning(f"RTSP流断开，尝试重新连接: {self.rtsp_url}")
                self.reconnect_attempts += 1
                success = self.start_capture()
                if not success:
                    # 如果重连失败，返回最后一帧或黑帧
                    if self.last_frame is not None:
                        return self._create_video_frame(self.last_frame)
                    else:
                        return self._create_black_frame()
            else:
                logger.error(f"RTSP流重连失败次数过多，停止重连: {self.rtsp_url}")
                if self.last_frame is not None:
                    return self._create_video_frame(self.last_frame)
                else:
                    return self._create_black_frame()
        
        # 尝试读取新帧
        try:
            # 清空缓冲区，获取最新帧
            for _ in range(5):  # 尝试清空缓冲区
                ret, frame = self.cap.read()
                if not ret:
                    break
                self.last_frame = frame
                self.last_frame_time = time.time()
            
            # 如果无法读取新帧，使用最后一帧
            if self.last_frame is None:
                return self._create_black_frame()
            
            # 创建视频帧
            video_frame = self._create_video_frame(self.last_frame)
            self.frame_counter += 1
            
            # 模拟帧率限制
            await asyncio.sleep(0.033)  # 约30FPS
            
            return video_frame
            
        except Exception as e:
            logger.error(f"读取视频帧失败: {e}")
            if self.last_frame is not None:
                return self._create_video_frame(self.last_frame)
            else:
                return self._create_black_frame()
    
    def _create_video_frame(self, frame):
        """
        创建视频帧
        
        Args:
            frame: OpenCV帧
            
        Returns:
            VideoFrame
        """
        # 将BGR格式转换为RGB格式
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        
        # 创建VideoFrame
        video_frame = VideoFrame.from_ndarray(frame, format="rgb24")
        video_frame.pts = self.frame_counter
        video_frame.time_base = fractions.Fraction(1, 30)  # 30 FPS
        
        return video_frame
    
    def _create_black_frame(self):
        """
        创建黑色视频帧
        
        Returns:
            VideoFrame
        """
        # 创建640x480的黑色帧
        frame = np.zeros((480, 640, 3), dtype=np.uint8)
        
        # 添加文本
        cv2.putText(
            frame,
            f"Stream disconnected: {self.stream_id}",
            (50, 240),
            cv2.FONT_HERSHEY_SIMPLEX,
            1,
            (255, 255, 255),
            2
        )
        
        return self._create_video_frame(frame)
    
    def stop(self):
        """停止视频流"""
        self.running = False
        if self.cap is not None:
            self.cap.release()
            self.cap = None
        logger.info(f"已停止RTSP流: {self.rtsp_url}")


class ProcessedVideoStreamTrack(MediaStreamTrack):
    """
    处理后视频流轨道，用于从StreamProcessor获取处理后的视频帧并转换为WebRTC
    """
    
    kind = "video"
    
    def __init__(self, stream_processor, stream_id: str):
        """
        初始化视频轨道
        
        Args:
            stream_processor: 视频流处理器
            stream_id: 流ID，用于标识
        """
        super().__init__()
        self.stream_processor = stream_processor
        self.stream_id = stream_id
        self.running = True
        self.frame_counter = 0
        self.last_frame = None
        self.last_frame_time = 0
        
    async def recv(self):
        """
        接收视频帧
        
        Returns:
            视频帧
        """
        if not self.running:
            raise Exception("视频流已停止")
        
        # 从处理器获取最新帧
        frame = self.stream_processor.get_latest_frame()
        
        # 如果没有帧，返回黑帧
        if frame is None:
            return self._create_black_frame()
            
        # 保存最后一帧
        self.last_frame = frame
        self.last_frame_time = time.time()
        
        # 创建视频帧
        video_frame = self._create_video_frame(frame)
        self.frame_counter += 1
        
        # 模拟帧率限制
        await asyncio.sleep(0.033)  # 约30FPS
        
        return video_frame
            
    def _create_video_frame(self, frame):
        """
        创建视频帧
        
        Args:
            frame: OpenCV帧
            
        Returns:
            VideoFrame
        """
        # 将BGR格式转换为RGB格式
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        
        # 创建VideoFrame
        video_frame = VideoFrame.from_ndarray(frame, format="rgb24")
        video_frame.pts = self.frame_counter
        video_frame.time_base = fractions.Fraction(1, 30)  # 30 FPS
        
        return video_frame
    
    def _create_black_frame(self):
        """
        创建黑色视频帧
        
        Returns:
            VideoFrame
        """
        # 创建640x480的黑色帧
        frame = np.zeros((480, 640, 3), dtype=np.uint8)
        
        # 添加文本
        cv2.putText(
            frame,
            f"Stream disconnected: {self.stream_id}",
            (50, 240),
            cv2.FONT_HERSHEY_SIMPLEX,
            1,
            (255, 255, 255),
            2
        )
        
        return self._create_video_frame(frame)
    
    def stop(self):
        """停止视频流"""
        self.running = False
        logger.info(f"已停止处理后视频流: {self.stream_id}")


class WebRTCServer:
    """WebRTC服务器，用于将RTSP视频流转换为WebRTC"""
    
    def __init__(self, host="0.0.0.0", port=8080):
        """
        初始化WebRTC服务器
        
        Args:
            host: 主机地址
            port: 端口号
        """
        self.host = host
        self.port = port
        self.app = web.Application()
        self.app.router.add_get("/", self.index)
        self.app.router.add_get("/client.js", self.javascript)
        self.app.router.add_post("/offer", self.offer)
        
        # 存储活跃的对等连接
        self.pcs = set()
        # 存储视频流轨道
        self.video_tracks: Dict[str, RTSPVideoStreamTrack] = {}
        # 存储RTSP URL
        self.rtsp_urls: Dict[str, str] = {}
    
    async def index(self, request):
        """
        处理根路径请求，返回HTML页面
        
        Args:
            request: HTTP请求
            
        Returns:
            HTTP响应
        """
        html = """
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>视频流监控系统</title>
            <style>
                body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
                h1 { color: #333; }
                .stream-container { display: flex; flex-wrap: wrap; gap: 20px; }
                .stream-box { margin-bottom: 20px; border: 1px solid #ddd; padding: 15px; border-radius: 5px; }
                .processed { background-color: #e6f7ff; border-color: #1890ff; }
                video { max-width: 640px; border: 1px solid #ccc; }
                button { padding: 8px 16px; background-color: #4CAF50; color: white; border: none; cursor: pointer; }
                button:hover { background-color: #45a049; }
                .stream-title { font-weight: bold; margin-bottom: 5px; }
                .stream-info { font-size: 12px; color: #666; margin-bottom: 10px; }
                .processed-badge { background-color: #1890ff; color: white; padding: 2px 8px; border-radius: 10px; font-size: 12px; }
            </style>
        </head>
        <body>
            <h1>视频流监控系统</h1>
            <div class="stream-container" id="streamContainer"></div>
            
            <script src="/client.js"></script>
        </body>
        </html>
        """
        return web.Response(content_type="text/html", text=html)
    
    async def javascript(self, request):
        """
        处理JavaScript请求，返回客户端脚本
        
        Args:
            request: HTTP请求
            
        Returns:
            HTTP响应
        """
        js = """
        // 获取可用的流列表
        async function getStreams() {
            try {
                const response = await fetch('/streams');
                return await response.json();
            } catch (e) {
                console.error('Error fetching streams:', e);
                return [];
            }
        }

        // 创建视频元素
        function createVideoElement(streamId, streamName, isProcessed, url) {
            const streamBox = document.createElement('div');
            streamBox.className = isProcessed ? 'stream-box processed' : 'stream-box';
            streamBox.id = `stream-box-${streamId}`;
            
            const title = document.createElement('div');
            title.className = 'stream-title';
            title.textContent = streamName || `Stream ${streamId}`;
            
            if (isProcessed) {
                const badge = document.createElement('span');
                badge.className = 'processed-badge';
                badge.textContent = '已处理';
                title.appendChild(document.createTextNode(' '));
                title.appendChild(badge);
            }
            
            const info = document.createElement('div');
            info.className = 'stream-info';
            info.textContent = isProcessed ? '带有检测框和人数统计的处理后视频流' : `原始RTSP流: ${url}`;
            
            const video = document.createElement('video');
            video.id = `video-${streamId}`;
            video.autoplay = true;
            video.playsInline = true;
            video.controls = true;
            
            const button = document.createElement('button');
            button.textContent = '开始观看';
            button.onclick = () => startStream(streamId);
            
            streamBox.appendChild(title);
            streamBox.appendChild(info);
            streamBox.appendChild(video);
            streamBox.appendChild(button);
            
            document.getElementById('streamContainer').appendChild(streamBox);
        }

        // 启动流
        async function startStream(streamId) {
            const video = document.getElementById(`video-${streamId}`);
            const button = video.nextElementSibling;
            button.disabled = true;
            button.textContent = 'Connecting...';
            
            try {
                // 创建对等连接
                const pc = new RTCPeerConnection({
                    sdpSemantics: 'unified-plan',
                    iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
                });
                
                // 处理ICE候选
                pc.onicecandidate = (event) => {
                    if (event.candidate) {
                        console.log('ICE candidate:', event.candidate);
                    }
                };
                
                // 处理连接状态变化
                pc.onconnectionstatechange = () => {
                    console.log(`Stream ${streamId} connection state:`, pc.connectionState);
                    if (pc.connectionState === 'failed') {
                        pc.close();
                        button.disabled = false;
                        button.textContent = 'Reconnect';
                    }
                };
                
                // 处理轨道
                pc.ontrack = (event) => {
                    if (event.track.kind === 'video') {
                        video.srcObject = event.streams[0];
                        button.textContent = 'Connected';
                    }
                };
                
                // 添加收发器
                pc.addTransceiver('video', { direction: 'recvonly' });
                
                // 创建提议
                const offer = await pc.createOffer();
                await pc.setLocalDescription(offer);
                
                // 发送提议到服务器
                const response = await fetch('/offer', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        sdp: pc.localDescription.sdp,
                        type: pc.localDescription.type,
                        stream_id: streamId
                    })
                });
                
                const answer = await response.json();
                await pc.setRemoteDescription(answer);
                
            } catch (e) {
                console.error(`Error starting stream ${streamId}:`, e);
                button.disabled = false;
                button.textContent = 'Retry';
            }
        }

        // 初始化页面
        async function initPage() {
            const streams = await getStreams();
            if (streams.length === 0) {
                document.getElementById('streamContainer').innerHTML = '<p>No streams available</p>';
                return;
            }
            
            streams.forEach(stream => {
                createVideoElement(stream.id, stream.name, stream.is_processed, stream.url);
            });
        }

        // 页面加载完成后初始化
        window.addEventListener('DOMContentLoaded', initPage);
        """
        return web.Response(content_type="application/javascript", text=js)
    
    async def offer(self, request):
        """
        处理WebRTC提议请求
        
        Args:
            request: HTTP请求
            
        Returns:
            HTTP响应
        """
        params = await request.json()
        offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])
        stream_id = params.get("stream_id")
        
        if not stream_id or stream_id not in self.rtsp_urls:
            return web.Response(
                content_type="application/json",
                text=json.dumps({"error": "Invalid stream ID"})
            )
        
        pc = RTCPeerConnection()
        self.pcs.add(pc)
        
        @pc.on("connectionstatechange")
        async def on_connectionstatechange():
            logger.info(f"Connection state for stream {stream_id}: {pc.connectionState}")
            if pc.connectionState == "failed" or pc.connectionState == "closed":
                await self.close_peer_connection(pc)
        
        # 获取或创建视频轨道
        if stream_id not in self.video_tracks:
            # 检查是否是处理后的视频流
            if self.rtsp_urls[stream_id].startswith("processed_stream_"):
                logger.warning(f"处理后视频流 {stream_id} 没有对应的视频轨道")
                return web.Response(
                    content_type="application/json",
                    text=json.dumps({"error": "Video track not available"})
                )
            else:
                # 创建RTSP视频轨道
                self.video_tracks[stream_id] = RTSPVideoStreamTrack(self.rtsp_urls[stream_id], stream_id)
        
        # 添加轨道到对等连接
        pc.addTrack(relay.subscribe(self.video_tracks[stream_id]))
        
        # 设置远程描述
        await pc.setRemoteDescription(offer)
        
        # 创建应答
        answer = await pc.createAnswer()
        await pc.setLocalDescription(answer)
        
        return web.Response(
            content_type="application/json",
            text=json.dumps({
                "sdp": pc.localDescription.sdp,
                "type": pc.localDescription.type
            })
        )
    
    async def get_streams(self, request):
        """
        处理获取流列表请求
        
        Args:
            request: HTTP请求
            
        Returns:
            HTTP响应
        """
        streams = []
        for stream_id, rtsp_url in self.rtsp_urls.items():
            # 检查是否是处理后的视频流
            is_processed = rtsp_url.startswith("processed_stream_")
            
            streams.append({
                "id": stream_id,
                "name": f"处理后视频流 {stream_id}" if is_processed else f"原始视频流 {stream_id}",
                "url": "处理后视频流" if is_processed else rtsp_url,
                "is_processed": is_processed
            })
        
        return web.Response(
            content_type="application/json",
            text=json.dumps(streams)
        )
    
    def add_stream(self, stream_id: str, rtsp_url: str, name: Optional[str] = None):
        """
        添加视频流
        
        Args:
            stream_id: 流ID
            rtsp_url: RTSP URL
            name: 流名称
        """
        self.rtsp_urls[stream_id] = rtsp_url
        logger.info(f"添加视频流: ID={stream_id}, URL={rtsp_url}")
        
    def add_processed_stream(self, stream_id: str, stream_processor, name: Optional[str] = None):
        """
        添加处理后的视频流
        
        Args:
            stream_id: 流ID
            stream_processor: 视频流处理器
            name: 流名称
        """
        # 存储处理后的视频流信息
        self.rtsp_urls[stream_id] = f"processed_stream_{stream_id}"  # 使用一个标识符，不是真正的URL
        
        # 如果已经有视频轨道，先停止它
        if stream_id in self.video_tracks:
            self.video_tracks[stream_id].stop()
        
        # 创建新的处理后视频轨道
        self.video_tracks[stream_id] = ProcessedVideoStreamTrack(stream_processor, stream_id)
        
        logger.info(f"添加处理后视频流: ID={stream_id}")
    
    def remove_stream(self, stream_id: str):
        """
        移除视频流
        
        Args:
            stream_id: 流ID
        """
        if stream_id in self.video_tracks:
            self.video_tracks[stream_id].stop()
            del self.video_tracks[stream_id]
        
        if stream_id in self.rtsp_urls:
            del self.rtsp_urls[stream_id]
        
        logger.info(f"移除视频流: ID={stream_id}")
    
    async def close_peer_connection(self, pc):
        """
        关闭对等连接
        
        Args:
            pc: 对等连接
        """
        await pc.close()
        self.pcs.discard(pc)
    
    async def close_all_connections(self):
        """关闭所有连接"""
        # 关闭所有对等连接
        coros = [self.close_peer_connection(pc) for pc in self.pcs]
        await asyncio.gather(*coros)
        self.pcs.clear()
        
        # 停止所有视频轨道
        for track in self.video_tracks.values():
            track.stop()
        self.video_tracks.clear()
        
        logger.info("已关闭所有WebRTC连接")
    
    def start(self):
        """启动WebRTC服务器"""
        # 添加获取流列表的路由
        self.app.router.add_get("/streams", self.get_streams)
        
        # 添加流页面路由
        self.app.router.add_get("/stream/{stream_id}", self.stream_page)
        
        # 添加WebSocket路由
        self.app.router.add_get("/ws/{stream_id}", self.websocket_handler)
        
        logger.info(f"启动WebRTC服务器: {self.host}:{self.port}")
        web.run_app(self.app, host=self.host, port=self.port)
    
    async def start_async(self):
        """异步启动WebRTC服务器"""
        # 添加获取流列表的路由
        self.app.router.add_get("/streams", self.get_streams)
        
        # 添加流页面路由
        self.app.router.add_get("/stream/{stream_id}", self.stream_page)
        
        # 添加WebSocket路由
        self.app.router.add_get("/ws/{stream_id}", self.websocket_handler)
        
        # 添加一个简单的状态页面
        self.app.router.add_get("/status", self.status_page)
        
        # 添加根路径重定向
        self.app.router.add_get("/", self.redirect_to_streams)
        
        runner = web.AppRunner(self.app)
        await runner.setup()
        site = web.TCPSite(runner, self.host, self.port)
        await site.start()
        logger.info(f"启动WebRTC服务器: {self.host}:{self.port}")
        return runner, site
        
    async def status_page(self, request):
        """
        返回服务器状态页面
        
        Args:
            request: HTTP请求
            
        Returns:
            HTTP响应
        """
        html = """
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>WebRTC Server Status</title>
        </head>
        <body>
            <h1>WebRTC Server Status</h1>
            <p>Server is running!</p>
            <p><a href="/streams">View available streams</a></p>
        </body>
        </html>
        """
        return web.Response(content_type="text/html", text=html)
        
    async def redirect_to_streams(self, request):
        """
        重定向到流列表页面
        
        Args:
            request: HTTP请求
            
        Returns:
            HTTP重定向
        """
        raise web.HTTPFound("/streams")
        
    async def stream_page(self, request):
        """
        处理单个流页面请求
        
        Args:
            request: HTTP请求
            
        Returns:
            HTTP响应
        """
        stream_id = request.match_info["stream_id"]
        
        if stream_id not in self.rtsp_urls:
            return web.Response(text=f"Stream {stream_id} not found", status=404)
        
        # 检查是否是处理后的视频流
        is_processed = self.rtsp_urls[stream_id].startswith("processed_stream_")
        stream_type = "处理后视频流" if is_processed else "原始视频流"
        
        html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>{stream_type} {stream_id}</title>
            <style>
                body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; }}
                h1 {{ color: #333; }}
                video {{ max-width: 100%; border: 1px solid #ccc; }}
                button {{ padding: 8px 16px; background-color: #4CAF50; color: white; border: none; cursor: pointer; }}
                button:hover {{ background-color: #45a049; }}
                .stream-info {{ background-color: #f5f5f5; padding: 10px; margin-bottom: 15px; border-radius: 5px; }}
                .processed {{ color: #1890ff; font-weight: bold; }}
            </style>
        </head>
        <body>
            <h1>{stream_type} {stream_id}</h1>
            <div class="stream-info">
                <p>{'<span class="processed">这是带有检测框和人数统计的处理后视频流</span>' if is_processed else f'原始RTSP流: {self.rtsp_urls[stream_id]}'}</p>
                <p>点击下方按钮开始观看视频流</p>
            </div>
            <video id="video" autoplay playsinline controls></video>
            <div>
                <button id="start">开始观看</button>
            </div>
            
            <script>
                const streamId = "{stream_id}";
                const video = document.getElementById('video');
                const startButton = document.getElementById('start');
                
                startButton.addEventListener('click', startStream);
                
                async function startStream() {{
                    startButton.disabled = true;
                    startButton.textContent = 'Connecting...';
                    
                    try {{
                        // 创建对等连接
                        const pc = new RTCPeerConnection({{
                            sdpSemantics: 'unified-plan',
                            iceServers: [{{ urls: 'stun:stun.l.google.com:19302' }}]
                        }});
                        
                        // 处理ICE候选
                        pc.onicecandidate = (event) => {{
                            if (event.candidate) {{
                                console.log('ICE candidate:', event.candidate);
                            }}
                        }};
                        
                        // 处理连接状态变化
                        pc.onconnectionstatechange = () => {{
                            console.log(`Connection state:`, pc.connectionState);
                            if (pc.connectionState === 'failed') {{
                                pc.close();
                                startButton.disabled = false;
                                startButton.textContent = 'Reconnect';
                            }}
                        }};
                        
                        // 处理轨道
                        pc.ontrack = (event) => {{
                            if (event.track.kind === 'video') {{
                                video.srcObject = event.streams[0];
                                startButton.textContent = 'Connected';
                            }}
                        }};
                        
                        // 添加收发器
                        pc.addTransceiver('video', {{ direction: 'recvonly' }});
                        
                        // 创建提议
                        const offer = await pc.createOffer();
                        await pc.setLocalDescription(offer);
                        
                        // 发送提议到服务器
                        const response = await fetch('/offer', {{
                            method: 'POST',
                            headers: {{ 'Content-Type': 'application/json' }},
                            body: JSON.stringify({{
                                sdp: pc.localDescription.sdp,
                                type: pc.localDescription.type,
                                stream_id: streamId
                            }})
                        }});
                        
                        const answer = await response.json();
                        await pc.setRemoteDescription(answer);
                        
                    }} catch (e) {{
                        console.error(`Error starting stream:`, e);
                        startButton.disabled = false;
                        startButton.textContent = 'Retry';
                    }}
                }}
                
                // 自动开始流
                window.addEventListener('DOMContentLoaded', startStream);
            </script>
        </body>
        </html>
        """
        return web.Response(content_type="text/html", text=html)
    
    async def websocket_handler(self, request):
        """
        处理WebSocket连接
        
        Args:
            request: HTTP请求
            
        Returns:
            WebSocket响应
        """
        ws = web.WebSocketResponse()
        await ws.prepare(request)
        
        stream_id = request.match_info["stream_id"]
        
        if stream_id not in self.rtsp_urls:
            await ws.close(code=4000, message=b"Stream not found")
            return ws
        
        # 这里应该实现WebSocket的处理逻辑，但这超出了本示例的范围
        
        await ws.close()
        return ws


if __name__ == "__main__":
    import numpy as np
    
    # 配置日志
    logging.basicConfig(level=logging.INFO)
    
    # 测试WebRTC服务器
    server = WebRTCServer()
    
    # 添加测试流
    server.add_stream("test1", "rtsp://admin:Lorytech2015@192.168.3.79:554/cam/realmonitor?channel=1&subtype=0", "Test Stream 1")
    
    # 启动服务器
    server.start()